package com.bucket.cloud.gateway.locator;

import com.alibaba.fastjson.JSON;
import com.bucket.cloud.gateway.event.GatewayRemoteRefreshRouteEvent;
import com.bucket.cloud.gateway.event.GatewayResourceRefreshEvent;
import com.bucket.cloud.gateway.service.feign.GatewayRouteServiceClient;
import com.bucket.cloud.system.api.model.SystemGatewayRouter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.event.RefreshRoutesEvent;
import org.springframework.cloud.gateway.filter.FilterDefinition;
import org.springframework.cloud.gateway.handler.predicate.PredicateDefinition;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationListener;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.util.UriComponentsBuilder;

import javax.annotation.Resource;
import java.net.URI;
import java.util.*;

import static com.bucket.cloud.gateway.repository.RedisRouteDefinitionRepository.GATEWAY_ROUTES;

@Slf4j
@Component
public class GatewayRouteLocator implements ApplicationListener<GatewayRemoteRefreshRouteEvent> {

    @Autowired
    private ApplicationEventPublisher publisher;

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Resource
    private GatewayRouteServiceClient gatewayRouteServiceClient;

    @Override
    public void onApplicationEvent(GatewayRemoteRefreshRouteEvent gatewayRemoteRefreshRouteEvent) {
        SystemGatewayRouter sgr = new SystemGatewayRouter();

        // 获取路由列表
        List<SystemGatewayRouter> list = gatewayRouteServiceClient.selectByParams(sgr);

        // 循环路由并加入到redis中
        for (SystemGatewayRouter d : list) {
            if (d.getState() == 1) {
                RouteDefinition definition = new RouteDefinition();

                // 设置ID
                definition.setId(d.getId());
                // 设置跳转地址
                URI uri = null;
                StringBuffer uriStr = new StringBuffer(d.getRoutType());
                uriStr.append("://");
                uriStr.append(d.getRoutUrl());
                if (d.getRoutType().equals("lb")) {
                    uri = UriComponentsBuilder.fromUriString(uriStr.toString()).build().toUri();
                } else {
                    uri = UriComponentsBuilder.fromHttpUrl(uriStr.toString()).build().toUri();
                }
                definition.setUri(uri);

                // 定义第一个断言
                PredicateDefinition predicate = new PredicateDefinition();
                predicate.setName("Path");

                Map<String, String> predicateParams = new HashMap<>(8);
//        predicateParams.put("pattern", "/cloud-auth");
                predicateParams.put("_genkey_0", d.getRoutPath());
                predicate.setArgs(predicateParams);

                definition.setPredicates(Arrays.asList(predicate));

                // ===定义Filter===
                List<FilterDefinition> filterList = new ArrayList<>();

                // 忽略前缀filter，忽略大于0才会配置
                if (d.getStripPrefix() > 0) {
                    FilterDefinition filter = new FilterDefinition();
                    filter.setName("StripPrefix");
                    Map<String, String> filterParams = new HashMap<>(8);
                    filterParams.put("_genkey_0", d.getStripPrefix().toString());
                    filter.setArgs(filterParams);
                    filterList.add(filter);
                }

                // 重试filter，重试次数大于0才会配置进去
                if (d.getRoutRetry() > 0) {
                    FilterDefinition filter2 = new FilterDefinition();
                    filter2.setName("Retry");
                    Map<String, String> filterParams2 = new HashMap<>(8);
                    filterParams2.put("retries", d.getRoutRetry().toString());
                    if (StringUtils.isNoneBlank(d.getRetrySeries())) {
                        filterParams2.put("series", d.getRetrySeries());
                    }
                    if (StringUtils.isNoneBlank(d.getRetryStatus())) {
                        filterParams2.put("statuses", d.getRetryStatus());
                    }
                    if (StringUtils.isNoneBlank(d.getRetryMethod())) {
                        filterParams2.put("methods", d.getRetryMethod());
                    }
                    if (StringUtils.isNoneBlank(d.getRetryExcep())) {
                        filterParams2.put("exceptions", d.getRetryExcep());
                    }
                    filter2.setArgs(filterParams2);
                    filterList.add(filter2);
                }

                if (filterList.size() > 0) {
                    definition.setFilters(filterList);
                }

                stringRedisTemplate.opsForHash().put(GATEWAY_ROUTES, d.getId(), JSON.toJSONString(definition));
            } else if (d.getState() == 0) {
                stringRedisTemplate.opsForHash().delete(GATEWAY_ROUTES, d.getId());
            }

        }

        log.info("=============加载动态路由:{}==============", list.size());

        this.publisher.publishEvent(new RefreshRoutesEvent(this));
        this.publisher.publishEvent(new GatewayResourceRefreshEvent(this));
    }
}
